/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Client.gui;

import Client.domain.ClientGameSession;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import javax.swing.JButton;
import javax.swing.JPanel;

/**
 *
 * @author Ripper
 */
public class GamePanel extends ClientPanel implements ActionListener, MouseListener, KeyListener
{
    private PlayPanel pp;
    private JButton disconnectButton;
    private boolean dm;
    
    private String typing;
    private boolean isTyping;
    
    private List<String> messages;
    private int messageIndex;
    private long lastReceivedMessage;
    
    private double cameraX;
    private double cameraY;
    
    private List<Effect> effects;
    
    public GamePanel(ClientWindow parent)
    {
        super(parent);
        setLayout(new BorderLayout());
        
        pp = new PlayPanel();
        add(pp, BorderLayout.CENTER);
        
        disconnectButton = new JButton(" Disconnect from game ");
        disconnectButton.addActionListener(this);
        disconnectButton.setFocusable(false);
        add(disconnectButton, BorderLayout.SOUTH);
        
        pp.addMouseListener(this);
        pp.addKeyListener(this);
        
        isTyping = false;
        typing = "";
        messages = new ArrayList<String>();
        effects = new ArrayList<Effect>();
    }
    
    public void tellServer(String msg)
    {
        getClientWindow().getClientDomainController().tellServer(msg);
    }
    
    public void updateGame(ClientGameSession cgs)
    {
        pp.setDataSource(cgs);
        repaint();
    }
    
    public void setDM(boolean val)
    {
        dm = val;
    }
    public boolean isDM()
    {
        return dm;
    }
    
    public void playerHasSpoken(String plr, String encodedMsg)
    {
        String decodedMsg = TextEncoder.decodeText(encodedMsg);
        
        String entireMessage = plr + ": " + decodedMsg;
        lastReceivedMessage = System.currentTimeMillis();
        messages.add(entireMessage);
        messageIndex = messages.size() - 1;
    }
    
    public void addTextEffect(Color c, int x, int y, String txt)
    {
        effects.add(new TextEffect(1000, txt, x, y, c));
    }

    @Override
    public void actionPerformed(ActionEvent e) 
    {
        if(e.getSource() == disconnectButton)
        {
            getClientWindow().disconnectFromSession();
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) { }

    @Override
    public void mousePressed(MouseEvent e) 
    { 
        if(pp.source != null && !isTyping)
        {
            //TODO
            //System.out.println("Click! @ "+e.getLocationOnScreen());
            try
            {
                Point modClick = e.getLocationOnScreen();
                Point screenLocation2 = this.getLocationOnScreen();
                modClick.translate((int)cameraX, (int)cameraY);
                modClick.translate(-(int)screenLocation2.x - (getWidth()/2), -(int)screenLocation2.y - (getHeight()/2));
                //System.out.println(modClick);
                tellServer("plrclick:"+modClick.x+","+modClick.y);
            }
            catch(Exception ex){}
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) { }
    @Override
    public void mouseEntered(MouseEvent e) { }
    @Override
    public void mouseExited(MouseEvent e) { }
    @Override
    public void keyTyped(KeyEvent e) 
    { 
        if(isDM() && !isTyping)
        {
            int movementSize = 10;
            switch(e.getKeyChar()) //keyTyped method always has 0 as keycode!
            {
                case 'q': //q
                case 'a': //a
                    //pp.source;
                    cameraX -= movementSize;
                    break;
                case 'z': //z
                case 'w': //w
                    cameraY -= movementSize;
                    break;
                case 's': //s
                    cameraY += movementSize;
                    break;
                case 'd': //d
                    cameraX += movementSize;
                    break;
            }
        }
    }

    @Override
    public void keyPressed(KeyEvent e) 
    {
        /*System.out.println("key pressed: Code:\""+e.getKeyCode()+"\" ExtendedCode:\""+e.getExtendedKeyCode()+"\" ID:\""+
                e.getID()+"\" char:\""+e.getKeyChar()+"\"");*/
        if(!isTyping)
        {
            switch(e.getKeyCode())
            {
                case 81: //q
                case 65: //a
                case 37: //left
                    //pp.source;
                    tellServer("movW=1");
                    break;
                case 90: //z
                case 87: //w
                case 38: //up
                    tellServer("movN=1");
                    break;
                case 83: //s
                case 40: //down
                    tellServer("movS=1");
                    break;
                case 68: //d
                case 39: //right
                    tellServer("movE=1");
                    break;
                case 32: //space

                    break;

                case 10: //enter
                    isTyping = true;
                    typing = "";
                    break;
                case 27: //escape

                    break;
                case 33: //page up
                    lastReceivedMessage = System.currentTimeMillis();
                    messageIndex -= 1;
                    if(messageIndex < 0)
                    {
                        messageIndex = 0;
                    }
                    break;
                case 34: //page down
                    lastReceivedMessage = System.currentTimeMillis();
                    messageIndex += 1;
                    if(messageIndex >= messages.size())
                    {
                        messageIndex = messages.size() - 1;
                    }
                    break;
            }
        }
        else
        {
            switch(e.getKeyCode())
            {
                case 10: //enter
                    isTyping = false;
                    if(typing.length() > 0)
                    {
                        String encoded = TextEncoder.encodeText(typing);
                        tellServer("plrsays:"+encoded);
                    }
                    break;
                case 27: //escape
                    //reset chat
                    isTyping = false;
                    typing = "";
                    break;
            }
            
            if(e.getKeyCode() == 32 || (e.getKeyCode() > 40 && e.getKeyCode() < 112))
            {
                typing += e.getKeyChar();
            }
            
            if(e.getKeyCode() == 8)
            {
                typing = typing.substring(0, typing.length()-1);
            }
        }
        //TODO
    }

    @Override
    public void keyReleased(KeyEvent e) 
    {        
        if(!isTyping)
        {
            switch(e.getKeyCode())
            {
                case 81: //q
                case 65: //a
                case 37: //left
                    //pp.source;
                    tellServer("movW=0");
                    break;
                case 90: //z
                case 87: //w
                case 38: //up
                    tellServer("movN=0");
                    break;
                case 83: //s
                case 40: //down
                    tellServer("movS=0");
                    break;
                case 68: //d
                case 39: //right
                    tellServer("movE=0");
                    break;
                case 32: //space

                    break;
            }
        }
    }
    
    private class PlayPanel extends JPanel
    {
        private ClientGameSession source;
        
        private PlayPanel()
        {
            
        }
        
        public void setDataSource(ClientGameSession cgs)
        {
            source = cgs;
        }
        
        public void paintDrawableObject(Graphics2D g, Drawable d)
        {
            boolean isSelecting = false;
            
            double x = d.getX();
            double y = d.getY();
            
            //determin if you're selecting this
            Point mouse = MouseInfo.getPointerInfo().getLocation();
            Point screenLocation2 = this.getLocationOnScreen();
            mouse.translate(-(int)screenLocation2.x - (getWidth()/2), -(int)screenLocation2.y - (getHeight()/2));
            mouse.translate((int)cameraX, (int)cameraY);
            if(mouse.x > x - 15 && mouse.x < x + 15 && mouse.y > y -15 && mouse.y < y + 15)
            {
                isSelecting = true;
            }
            
            BufferedImage bi = (isSelecting?d.getImageToDrawWhenSelecting():d.getImageToDraw());
            g.translate(x, y);
            g.rotate(d.getRotation());
            g.drawImage(bi, - (bi.getWidth()/2),  - (bi.getHeight()/2), this);
            /*g.setColor(Color.RED);
            g.drawLine(-2, -2, 2, 2);
            g.drawLine(-2,2,2,-2);*/
            g.rotate(-d.getRotation());
            g.translate(-(x), -(y));
            
            if(d.getName().length() > 0)
            {
                //name
                g.setColor(Color.WHITE);
                g.drawString(d.getName(), (int)x - 52, (int)y - 70);
            }
            
            if(d.getHpprct() != -1)
            {
                //HP BAR
                g.setColor(Color.BLACK);
                g.fillRect((int)x - 52, (int)y - 60, 104, 14);
                g.setColor(Color.GREEN);
                g.drawRect((int)x - 50, (int)y - 58, 100, 10);
                g.fillRect((int)x - 50, (int)y - 58, d.getHpprct(), 10);
            }
        }
        
        @Override
        public void paintComponent(Graphics g)
        {
            if(source != null)
            {
                if(g instanceof Graphics2D)
                {
                    Graphics2D gg = (Graphics2D)g;
                    gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    gg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

                    gg.setColor(Color.DARK_GRAY);
                    gg.fillRect(0, 0, getWidth(), getHeight());
                    
                    if(!isDM())
                    {
                        cameraX = source.getActivePlayersX();
                        cameraY = source.getActivePlayersY();
                    }
                    
                    double tx = -cameraX + (getWidth() / 2);
                    double ty = -cameraY + (getHeight() / 2);
                    
                    gg.translate(tx, ty);

                    //draw tile
                    for(Drawable d: source.getTiles())
                    {
                        try
                        {
                            paintDrawableObject(gg,d);
                        }catch(Exception ex) {ex.printStackTrace();}
                    }
                    //draw decorative elements
                    for(Drawable de: source.getDecorativeElements())
                    {
                        try
                        {
                            paintDrawableObject(gg,de);
                        }catch(Exception ex) {ex.printStackTrace();}
                    }
                    //draw monsters
                    for(Drawable d: source.getDrawableMonsters())
                    {
                        try
                        {
                            paintDrawableObject(gg,d);
                        }catch(Exception ex) {ex.printStackTrace();}
                    }
                    //draw players
                    for(Drawable d: source.getDrawablePlayers())
                    {
                        try
                        {
                            paintDrawableObject(gg,d);
                        }catch(Exception ex) {ex.printStackTrace();}
                    }
                    //draw projectiles
                    for(Drawable d: source.getProjectiles())
                    {
                        try
                        {
                            paintDrawableObject(gg,d);
                        }catch(Exception ex) {ex.printStackTrace();}
                    }

                    //Color[] colors = {new Color()};
                    //gg.drawImage(getClientWindow().getClientDomainController().getImage(10000, colors), 0, 0, this);
                    
                    //draw effects
                    Font f = gg.getFont();
                    Font f2 = new Font(f.getFontName(), Font.BOLD, f.getSize());
                    gg.setFont(f2);
                    for(Effect e: effects)
                    {
                        e.draw(gg);
                    }
                    ListIterator<Effect> i = effects.listIterator();
                    while(i.hasNext())
                    {
                        Effect e = i.next();
                        if(!e.isAlive())
                        {
                            i.remove();
                        }
                    }
                    gg.setFont(f);
                    
                    gg.translate(-tx, -ty);
                    
                    if(!isDM())
                    {
                        //draw gui
                        gg.setColor(Color.BLACK);
                        gg.fillRect(0,getHeight()-70,140,70);
                        gg.setColor(Color.RED);
                        gg.drawRect(30, getHeight()-65, 100, 15);
                        gg.fillRect(30, getHeight()-65, source.getHPprct(), 15);
                        gg.setColor(Color.GREEN);
                        gg.drawRect(30, getHeight()-45, 100, 15);
                        gg.fillRect(30, getHeight()-45, source.getSPprct(), 15);
                        gg.setColor(Color.BLUE);
                        gg.drawRect(30, getHeight()-25, 100, 15);
                        gg.fillRect(30, getHeight()-25, source.getMPprct(), 15);

                        gg.setColor(Color.BLACK);
                        gg.drawString(source.getHitpoints() + " / " + source.getMaxhitpoints(), 30+35, getHeight()-53);
                        gg.drawString(source.getManapoints() + " / " + source.getMaxmanapoints(), 30+35, getHeight()-33);
                        gg.setColor(Color.WHITE);
                        gg.drawString(source.getStaminapoints() + " / " + source.getMaxstaminapoints(), 30+35, getHeight()-13);
                    }
                    
                    if(isTyping)
                    {
                        //draw what you're typing:
                        gg.setColor(Color.WHITE);
                        gg.drawString("Talk: "+typing, 200, getHeight()-200);
                    }
                    
                    if(lastReceivedMessage > System.currentTimeMillis() - 4000 || isTyping) //messages show for 4 seconds
                    {
                        gg.setColor(Color.WHITE);
                        int idx = 0;
                        int numberOfMessagesToShow = 10;
                        int spaceBetweenMessages = 14;
                        for(idx = 0; idx < numberOfMessagesToShow; idx++)
                        {   
                            int idxToDraw = messageIndex-idx;

                            try
                            {
                                gg.drawString(""+messages.get(idxToDraw),200,getHeight()-210-spaceBetweenMessages*(idx+1));
                            }catch(Exception ex){}
                        }
                    }
                }
            }
            else
            {
                g.drawString("No data source found", 10, 10);
            }
        }
    }
}
